//!
/**
 ***********************************************************************************************************
 * <RBEffectFactory implementation>
 ***********************************************************************************************************
 * @file RBEffectFactory.cpp
 ***********************************************************************************************************/

/************************************************************************************************************
 * Includes
 ************************************************************************************************************/
#include "RBEffectFactory.h"

#include "RBEffect.h"
#include "RBEffectCompiler.h"

#define MATERIAL_EXT "fxm"

const char* const RBEffectFactory::ms_shader_ext = "hlsl";
const char* const RBEffectFactory::ms_material_ext = MATERIAL_EXT;

/************************************************************************************************************/

/***********************************************************************************************************
 * 
 ***********************************************************************************************************/
RBEffectFactory::~RBEffectFactory()
{
    for (uint32 ui=0; ui < m_vCompilers.size(); ++ui)
    {
        delete m_vCompilers[ui];
    }
}

/***********************************************************************************************************
 * 
 ***********************************************************************************************************/
void RBEffectFactory::AddDirectory( const RBString& strDirectory )
{
    m_vDirectories.push_back(strDirectory);
}

/***********************************************************************************************************
 * 
 ***********************************************************************************************************/
void RBEffectFactory::AddCompiler( RBEffectCompiler* pCompiler )
{
    m_vCompilers.push_back(pCompiler);
}

class RBEffectFinder : public RBSystem::File::FileIterator
{
public:
    RBEffectFinder(RBEffectFactory* pFactory) : m_pFactory(pFactory) {}

    // Callback called on file
    virtual void OnFile(const RBString& strName);

    RBEffectFactory* m_pFactory;
};

/***********************************************************************************************************
 * 
 ***********************************************************************************************************/
void RBEffectFinder::OnFile( const RBString& strName )
{
    m_pFactory->AddEffect(strName);
}

/***********************************************************************************************************
 * 
 ***********************************************************************************************************/
void RBEffectFactory::Parse()
{
    for (uint32 uiDir=0; uiDir < m_vDirectories.size(); ++uiDir)
    {
        RBSystem::File::ParseDirectory(m_vDirectories[uiDir], RBEffectFinder(this), "*." MATERIAL_EXT);
    }
}

/***********************************************************************************************************
 * 
 ***********************************************************************************************************/
RBEffect* RBEffectFactory::RetrieveEffect( const RBString& strEffectName )
{
    RBEffect* pEffect = NULL;
    for (uint32 uiCompiler=0; (uiCompiler < m_vCompilers.size()) && (pEffect == NULL); ++uiCompiler)
    {
        pEffect = m_vCompilers[uiCompiler]->RetrieveEffect(strEffectName);
    }

    return pEffect;

}

/***********************************************************************************************************
 * 
 ***********************************************************************************************************/
void RBEffectFactory::AddEffect( const RBString& strFilename )
{
    for (uint32 uiCompiler=0; uiCompiler < m_vCompilers.size(); ++uiCompiler)
    {
        m_vCompilers[uiCompiler]->Compile(strFilename);
    }
}

/***********************************************************************************************************
 * 
 ***********************************************************************************************************/
void RBEffectFactory::GetDirectories( std::vector<RBString>& vDirectories )
{
    vDirectories = m_vDirectories;
}

/***********************************************************************************************************
 * 
 ***********************************************************************************************************/
void RBEffectFactory::Reset( bool bBeforeReset )
{
    for (uint32 uiCompiler=0; uiCompiler < m_vCompilers.size(); ++uiCompiler)
    {
        m_vCompilers[uiCompiler]->Reset(bBeforeReset);
    }
}
